package excel

import (
	"bufio"
	"container/list"
	"encoding/csv"
	"os"

	"github.com/astaxie/beego/logs"
	"github.com/extrame/xls"
	"github.com/tealeg/xlsx"
)

// @author https://github.com/fuadajip/golang-excel-parser
// ReadCSVFile will parse csv file
func ReadCSVFile(filePath string, headName []string) ([]map[string]interface{}, error) {
	f, _ := os.Open(filePath)

	r := csv.NewReader(bufio.NewReader(f))

	result, err := r.ReadAll()
	if err != nil {
		logs.Error("读取号码失败:%v", err)
		return nil, err
	}

	parsedData := make([]map[string]interface{}, 0, 0)
	var headerName = result[0]
	var skipFirst = true
	if headName != nil {
		headerName = headName
		skipFirst = false
	}
	for rowCounter, row := range result {
		if !skipFirst || rowCounter != 0 {
			var singleMap = make(map[string]interface{})

			for colCounter, col := range row {
				singleMap[headerName[colCounter]] = col

			}
			if len(singleMap) > 0 {
				parsedData = append(parsedData, singleMap)
			}
		}
	}

	logs.Debug("Length of parsedData:", len(parsedData))
	return parsedData, nil
}

func ReadCSVFileWithoutHeaderName(filePath string) ([]map[string]interface{}, error) {
	return ReadCSVFile(filePath, []string{"_"})
}

func ReadCSVFileHeaderName(filePath string, headName []string) ([]map[string]interface{}, error) {
	return ReadCSVFile(filePath, headName)
}

// ReadXLSXFile will parse xlsx file
func ReadXLSXFile(filePath string, headName []string) ([]map[string]interface{}, error) {
	xlFile, err := xlsx.OpenFile(filePath)
	if err != nil {
		logs.Debug("Error reading the file")
	}

	parsedData := make([]map[string]interface{}, 0, 0)
	headerName := list.New()

	var skipFirst = true

	if headName != nil {
		for _, name := range headName {
			headerName.PushBack(name)
		}
		skipFirst = false
	}

	// iterate sheet
	for _, sheet := range xlFile.Sheets {
		// iterate rows
		for rowCounter, row := range sheet.Rows {

			// iterates column
			headerIterator := headerName.Front()
			var singleMap = make(map[string]interface{})

			for _, cell := range row.Cells {
				if rowCounter != 0 || !skipFirst {
					text := cell.String()
					singleMap[headerIterator.Value.(string)] = text
					headerIterator = headerIterator.Next()
				} else {
					text := cell.String()
					headerName.PushBack(text)
				}
			}
			if len(singleMap) > 0 {

				parsedData = append(parsedData, singleMap)
			}

		}
	}
	logs.Debug("Length of parsedData:", len(parsedData))
	return parsedData, nil
}

// ReadXLSXFile will parse xlsx file
func ReadXLSFile(filePath string, headName []string) ([]map[string]interface{}, error) {

	parsedData := make([]map[string]interface{}, 0, 0)
	headerName := list.New()

	var skipFirst = true

	if headName != nil {
		for _, name := range headName {
			headerName.PushBack(name)
		}
		skipFirst = false
	}

	if xlFile, err := xls.Open(filePath, "utf-8"); err == nil {
		for sheetIndex := 0; sheetIndex <= (int(xlFile.NumSheets())); sheetIndex++ {
			if sheet1 := xlFile.GetSheet(sheetIndex); sheet1 != nil {
				logs.Debug("Total Lines ", sheet1.MaxRow, sheet1.Name)
				for rowCounter := 0; rowCounter <= (int(sheet1.MaxRow)); rowCounter++ {

					headerIterator := headerName.Front()
					var singleMap = make(map[string]interface{})

					row := sheet1.Row(rowCounter)
					for rowColIndex := row.FirstCol(); rowColIndex < row.LastCol(); rowColIndex++ {
						// 第一行 并且 跳过
						if rowCounter != 0 || !skipFirst {
							text := row.Col(rowColIndex)
							singleMap[headerIterator.Value.(string)] = text
							headerIterator = headerIterator.Next()
						} else {
							headName := row.Col(rowColIndex)
							headerName.PushBack(headName)
						}
					}
					if len(singleMap) > 0 {
						parsedData = append(parsedData, singleMap)
					}
				}

			}
		}

	}

	return parsedData, nil
}

// ExcelCSVParser will act as main function to extract excel and csv file
func ExcelCSVParser(blobPath string, blobExtension string, headName []string) (parsedData []map[string]interface{}, err error) {
	logs.Debug("ExcelCSVParser [ blobPath=%v ],[blobExtension=%v][headName=%v]", blobPath, blobExtension, headName)
	if blobExtension == ".csv" || blobExtension == ".txt" {
		parsedData, err := ReadCSVFile(blobPath, headName)
		logs.Debug("Type:%T\n", parsedData)
		if err != nil {
			logs.Error("err failed %v , path:%v", err)
			return nil, err
		}

		return parsedData, nil

	} else if blobExtension == ".xlsx" {
		parsedData, err := ReadXLSXFile(blobPath, headName)
		if err != nil {
			logs.Error("err failed %v , path:%v", err)
			return nil, err
		}
		logs.Debug("Type:%T\n", parsedData)
		return parsedData, nil
	} else if blobExtension == ".xls" {
		parsedData, err := ReadXLSFile(blobPath, headName)
		if err != nil {
			logs.Error("err failed %v , path:%v", err)
			return nil, err
		}
		logs.Debug("Type:%T\n", parsedData)
		return parsedData, nil
	}
	return parsedData, nil
}

//
//func ExcelCSVParserWithoutHeaderName(blobPath string, blobExtension string) (parsedData []map[string]interface{}) {
//	if blobExtension == ".csv" {
//		parsedData := R(blobPath)
//		fmt.Printf("Type:%T\n", parsedData)
//		return parsedData
//
//	} else if blobExtension == ".xlsx" {
//		parsedData := ReadXLSXFile(blobPath,nil)
//		fmt.Printf("Type:%T\n", parsedData)
//		return parsedData
//	}
//	return parsedData
//}
